package com.ydlclass.utils.zookeeper;

import com.ydlclass.Constant;
import com.ydlclass.exceptions.ZookeeperException;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * @author Knife
 */
@Slf4j
public class ZookeeperUtil {
    /**
     * 使用默认配置创建zookeeper实例
     * @return
     */
    public static ZooKeeper creatZookeeper(){
        // 定义连接参数
        String connectString = Constant.DEFAULT_ZK_CONNECT;
        // 定义超时时间
        int timeout = Constant.TIME_OUT;
        return creatZookeeper(connectString,timeout);
    }
    public static ZooKeeper creatZookeeper(String connectString,int timeout) {
        CountDownLatch countDownLatch = new CountDownLatch(1);

        try {
            final ZooKeeper zooKeeper = new ZooKeeper(connectString, timeout, event -> {
                if (event.getState() == Watcher.Event.KeeperState.SyncConnected) {
                    log.debug("客户端已经连接成功");
                    countDownLatch.countDown();
                }
            });

            countDownLatch.await();
            return zooKeeper;
        } catch (IOException | InterruptedException e) {
            log.error("创建zookeeper实例时发生:{}", e);
            throw new ZookeeperException();
        }
    }

    /**
     * 用来创建一个节点的工具方法
     * @param zookeeper zookeeper实例
     * @param zookeeperNode 节点
     * @param watcher watcher实例
     * @param createMode 节点的类型
     * @return true :成功创建  false : 已经存在，或者抛出异常
     */
    public static boolean creatNode(ZooKeeper zookeeper,ZookeeperNode zookeeperNode,Watcher watcher,CreateMode createMode){
        try {
            if (zookeeper.exists(zookeeperNode.getNodePath(), watcher) == null) {
                String result = zookeeper.create(zookeeperNode.getNodePath(), zookeeperNode.getData(), ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode);
                log.debug("根节点{},成功创建", result);
                return true;
            } else {
                if (log.isDebugEnabled()){
                    log.debug("根节点{},已经存在，无需创建", zookeeperNode.getNodePath());

                }
                return false;
            }
        } catch (KeeperException | InterruptedException e) {
            log.error("创建基础目录时发生异常:{}", e);
            throw new ZookeeperException();
        }
    }

    /**
     *  关闭zookeeper的方法
     * @param zooKeeper 传入的zookeeper
     */
    public static void close(ZooKeeper zooKeeper){
        try {
            zooKeeper.close();
        } catch (InterruptedException e) {
            log.error("关闭zookeeper时发生问题:{}",e);
            throw new ZookeeperException();
        }
    }

    /**
     * 判断节点是否存在
     * @param zk zookeeper
     * @param node 节点路径
     * @param watcher watcher
     * @return true 存在 ;false 不存在
     */
    public static boolean exists(ZooKeeper zk,String node,Watcher watcher) {
        try {
            return  zk.exists(node,watcher)!=null;
        } catch (KeeperException | InterruptedException e) {
            log.debug("判断节点:{},存在发生异常:{}",node,e);
            throw new ZookeeperException(e);
        }
    }

    /**
     * 查询一个节点的子元素
     * @param zooKeeper zk实例
     * @param serviceNode 服务节点
     * @return
     */
    public static List<String> getChildren(ZooKeeper zooKeeper, String serviceNode,Watcher watcher) {
        try {
            return zooKeeper.getChildren(serviceNode, watcher);
        } catch (KeeperException | InterruptedException e) {
            log.error("获取节点{}的子元素时发生异常{}",serviceNode,e);
            throw new ZookeeperException(e);
        }
    }
}
